<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>可视化音频</title>
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <style>
	body {
		display: block;
		background: url("../img/1.jpg");
		background-position: center;
		background-repeat: no-repeat;
		background-attachment: fixed;
		background-size:100%;
	}
	.div1{
		width: 200px;
		height: 100px;
		background: #fff;
		opacity: 0.3;
	}
  </style>
 </head>
 <body>
 <div class="div1">
 </div>
 
  <input type="file" style="color:red;" name="" value="" id="musicFile"><input type="button" name="startStop" value="暂停" id="startStop">
	<p id="tip" style="color:red;"></p>
	<canvas id="canvas"></canvas>
    <script>
	    window.onload = function () {
	    	canvas.width = window.innerWidth;
	    	canvas.height = window.innerHeight;
	    	var canvasCtx = canvas.getContext("2d");
	    	
	    	var AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
	    	var audioContext = new AudioContext();//实例化
	    	
	    	$('#musicFile').change(function(){
				//当选择歌曲时，判断当前audioContext的状态，如果在进行中则关闭音频环境，
				//释放audioContext的所有资源，并重新实例化audioContext
				if(audioContext.state == 'running'){
					audioContext.close();
					audioContext = new AudioContext();
				}

	    		if (this.files.length == 0) return;
	    		var file = $('#musicFile')[0].files[0];
	    		var fileReader = new FileReader();
	    		fileReader.readAsArrayBuffer(file);
	    		fileReader.onload = function(e) {
	    			var count = 0;
	    			$('#tip').text('开始解码')
	    			var timer = setInterval(function(){
	    				count++;
	    				$('#tip').text('解码中,已用时'+count+'秒')
	    			},1000)
	    			audioContext.decodeAudioData(e.target.result, function(buffer) {
	    				clearInterval(timer)
	    				$('#tip').text('解码成功，用时共计:'+count+'秒')
	    				var audioBufferSourceNode = audioContext.createBufferSource();
	    				var analyser = audioContext.createAnalyser();
	    				analyser.fftSize = 256;
						audioBufferSourceNode.connect(analyser);
						analyser.connect(audioContext.destination);
						audioBufferSourceNode.buffer = buffer;
						audioBufferSourceNode.start();
						var bufferLength = analyser.frequencyBinCount;
						var dataArray = new Uint8Array(bufferLength);

						//播放暂停音频
						startStop.onclick = function() {
							if(audioContext.state === 'running') {
									audioContext.suspend().then(function() {
									$("#startStop").val('播放');
								});
							} else if(audioContext.state === 'suspended') {
									audioContext.resume().then(function() {
									$("#startStop").val('暂停');
								});  
							}
						}
						
						var oW = canvas.width;
						var oH = canvas.height;
						var color1 = canvasCtx.createLinearGradient(oW / 2, oH / 2-10, oW / 2, oH / 2 - 150);
						var color2 = canvasCtx.createLinearGradient(oW / 2, oH / 2+10, oW / 2, oH / 2 + 150);
						color1.addColorStop(0, '#1E90FF');
						color1.addColorStop(.25, '#FF7F50');
						color1.addColorStop(.5, '#8A2BE2');
						color1.addColorStop(.75, '#4169E1');
						color1.addColorStop(1, '#00FFFF');
						
						color2.addColorStop(0, '#1E90FF');
						color2.addColorStop(.25, '#FFD700');
						color2.addColorStop(.5, '#8A2BE2');
						color2.addColorStop(.75, '#4169E1');
						color2.addColorStop(1, '#FF0000');
						function draw() {
							drawVisual = requestAnimationFrame(draw);
							var barHeight;
					        // 自定义获取数组里边数据的频步
					        canvasCtx.clearRect(0, 0, oW, oH);
					        for (var i = 0; i < bufferLength; i++) {
					        	barHeight = dataArray[i];
					        	analyser.getByteFrequencyData(dataArray);
								canvasCtx.fillStyle = color1;  // 绘制向上的线条
								canvasCtx.fillRect(oW / 2 + (i * 8), oH / 2, 4, -barHeight);
					          	canvasCtx.fillRect(oW / 2 - (i * 8), oH / 2, 4, -barHeight);
					          	canvasCtx.fillStyle = color2;  // 绘制向下的线条
					          	canvasCtx.fillRect(oW / 2 + (i * 8), oH / 2, 2, barHeight);
					          	canvasCtx.fillRect(oW / 2 - (i * 8), oH / 2, 2, barHeight);
					        }
						};
						draw();
	    			})
	    		}
	    	})
	    }
    </script>
 </body>
</html>
